#include "../include/scNet/Server.hpp"

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdexcept>
#include <thread>
#include <fcntl.h>

namespace scNet {
	// 构造函数：初始化默认的请求处理器和错误处理器
	Server::Server() {
		// 默认的请求处理器 返回 OK 响应
		request_handler_ = [](const std::string&) {
			return "OK";
		};
		// 默认错误处理器 错误信息抛出为异常
		error_handler_ = [](const std::string& err) {
			throw std::runtime_error(err);
		};
	}

	// 析构函数：调用stop()方法停止服务器并清理资源
	Server::~Server() {
		stop();
	}

	// 继承来自ServerCore的接口
	// 启动服务器 指定端口号
	void Server::start(uint16_t port) {
		if (running_)	
			return;	// 如果服务器已在运行，则不再启动

		try {
			// 创建一个新的套接字 IPv4 TCP方式
			socket_ = std::make_unique<SocketWrapper>(AF_INET, SOCK_STREAM);
			// 设置端口复用，允许重新绑定相同端口
        	int opt = 1;
        	setsockopt(socket_->getFd(), SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

			// 服务器的地址信息
			sockaddr_in addr{};
			addr.sin_family = AF_INET;               // 使用IPv4协议
        	addr.sin_addr.s_addr = INADDR_ANY;       // 监听任意可用的网络接口
        	addr.sin_port = htons(port);             // 设置监听的端口号

			// 套接字绑定到指定 地址和端口
			socket_->bind(reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
			// 监听客户端连接 最大排队数128
			socket_->listen(128);
			// 给非阻塞
			socket_->setNonBlocking(true);
			// 更新服务器状态
			running_ = true;
			// 启动一个新的线程来处理客户端连接请求
        	thread_pool_.enqueue([this] { acceptConnections(); });
		} catch (const std::exception& e) {
			error_handler_(std::string("Server start failed: ") + e.what());
		}
	}

	// 停止服务器
	void Server::stop() {
		running_ = false;	// 更新服务器状态 停止
		if (socket_) {
			socket_.reset();	// 释放socket
		}
	}

	// 设置请求处理函数 用于处理接受到的请求
	void Server::setRequestHandler(std::function<std::string(const std::string&)> handler)	{
		request_handler_ = handler;
	}
	
	// 设置连接处理函数，用于处理客户端连接
	void Server::setConnectionHandler(std::function<void(int)> handler) {
		connection_handler_ = handler;
	}
	
	// 设置错误处理函数，用于处理服务器错误
	void Server::setErrorHandler(std::function<void(const std::string&)> handler) {
		error_handler_ = handler;
	}

	// 接受客户端连接
	void Server::acceptConnections() {
		while (running_) {
			// 服务器在运行，就持续接受连接
			try {
				sockaddr_in client_addr{};
				socklen_t addr_len = sizeof(client_addr);
				// 接受 客户端连接
				int client_fd = socket_->accept(reinterpret_cast<sockaddr*>(&client_addr), &addr_len);

				// 连接成功 client_fd > 0
				if (client_fd > 0) {
					// 有连接处理器 调用
					if (connection_handler_)	
						connection_handler_(client_fd);
					
					// 客户端分配的处理任务 分配到 线程池
					thread_pool_.enqueue([this, client_fd] { handleClient(client_fd); });
				} else {
					// 避免cpu占用过高 （长时间没有客户端连接的情况）
					// 处理非阻塞模式下的 EAGAIN/EWOULDBLOCK 错误
					if (errno == EAGAIN || errno == EWOULDBLOCK) {
						std::this_thread::sleep_for(std::chrono::milliseconds(100));
						continue;
					}
					// 抛错误 接受连接失败
					throw std::system_error(errno, std::generic_category(), "Accept failed");
				}
			} catch (std::exception& e) {
				error_handler_(std::string("Accept connection failed: ") + e.what());		// 如果接受连接过程中发生错误，调用错误处理器
			}
		}
	}

	// 处理与客户端的通信 接收请求，调用处理器处理请求，发送响应
	void Server::handleClient(int client_fd) {
		// 首先调用封装好的 套接字操作类 合理使用作用域来管理 客户端连接
		SocketWrapper client_socket(client_fd);	
		try {
			// 接收数据的缓冲区
			char buf[4096];
			while (true) {
				ssize_t bytes_read = client_socket.recv(buf, sizeof(buf));
				if (bytes_read <= 0) break;  // 如果没有数据，则退出
				
				// 接收到的数据都转成string 
				std::string request(buf, bytes_read);
				// 请求处理器来处理转换后的字符串请求 GET 响应
				std::string response = request_handler_(request);
				// 得到的响应给服务端 实现 互通
				client_socket.send(response.data(), response.size());
			}
		} catch (const std::exception& e) {
			error_handler_(std::string("Handle client failed: ") + e.what());
		}
	}
}